package org.jeecg.modules.oms.parser.impl.optimization;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.jeecg.modules.oms.entity.*;
import org.jeecg.modules.oms.parser.OptimizationFileProcessor;
import org.jeecg.modules.oms.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.*;

/**
 * 长风优化单处理器
 */
@Slf4j
@Component
public class ChangfengOptimizationFileProcessor implements OptimizationFileProcessor {

    @Autowired
    private IProductSalesOrderService productSalesOrderService;
    
    @Autowired
    private ICfProfileMaterialService cfProfileMaterialService;
    
    @Autowired
    private ICfProfileCutDetailService cfProfileCutDetailService;
    
    @Autowired
    private ICfProfileWorkDetailService cfProfileWorkDetailService;

    @Autowired
    private IProductSalesOrderProgressService productSalesOrderProgressService;

    @Autowired
    private IDesignFileService designFileService;

    @Override
    public boolean processOptimizationFile(String orderId, MultipartFile file, String userId, String userName,List<ProductSalesOrder> orders) {
        try {
            // 验证文件类型
            if (!file.getOriginalFilename().toLowerCase().endsWith(".xml")) {
                log.error("文件格式错误，仅支持XML文件");
                return false;
            }

            // 获取订单信息  修改为根据orderId获取订单列表  并拼接orderNo
            String[] orderIdArray = orderId.split(",");
            ArrayList<String> orderNoList = new ArrayList<>();
            for (ProductSalesOrder order : orders){
                if (order == null) {
                    log.error("未找到订单, 订单ID: {}", orderId);
                    return false;
                }else {
                    orderNoList.add(order.getOrderNo());
                }
            }
            
            // 解析XML文件
            Map<String, Object> xmlData = parseXmlFile(file);
            if (xmlData == null || xmlData.isEmpty()) {
                log.error("XML文件解析失败");
                return false;
            }
            
            // 先删除已有的数据
            cfProfileMaterialService.deleteByOrderId(orderId);
            cfProfileCutDetailService.deleteByOrderId(orderId);
            cfProfileWorkDetailService.deleteByOrderId(orderId);
            
            // 保存型材信息及关联数据
            ProductSalesOrder order = new ProductSalesOrder();
            order.setId(String.join(",", orderIdArray));
            order.setOrderNo(String.join(",", orderNoList));
            int[] result = saveAllData(xmlData, order, userId, userName);

            // 调用designFileService保存优化单文件
            try {
                boolean fileSuccess = designFileService.uploadOptimizationFile(orderId, file, userId, userName);
                if (!fileSuccess) {
                    log.warn("保存优化单文件记录失败, 订单ID: {}", orderId);
                    // 不影响主流程，继续执行
                }
            } catch (Exception e) {
                log.error("保存优化单文件记录异常, 订单ID: {}", orderId, e);
                // 不影响主流程，继续执行
            }


            for (String id : orderIdArray) {
                ProductSalesOrder orderById = productSalesOrderService.getById(id);
                Integer oldStatus = orderById.getStatus();
                if (oldStatus != null) { // 确保当前状态为"已上传汇总单-待上传优化单"
                    orderById.setStatus(3); // 更新为"已上传优化单-待提交审核"
                    productSalesOrderService.updateById(orderById);

                    // 记录订单进度
                    try {
                        // 创建订单进度记录
                        ProductSalesOrderProgress progress = new ProductSalesOrderProgress();
                        progress.setOrderId(id);
                        progress.setOldStatus(oldStatus);
                        progress.setNewStatus(3);
                        progress.setChangeTime(new Date());
                        progress.setOperatorId(userId);
                        progress.setOperatorName(userName);
                        progress.setChangeReason("上传优化单");
                        productSalesOrderProgressService.save(progress);
                    } catch (Exception e) {
                        // 进度记录失败不影响主流程
                        log.error("记录订单进度失败", e);
                    }
                }
            }
            
        return true;
        } catch (Exception e) {
            log.error("处理长风优化文件出错", e);
            return false;
        }
    }
    
    /**
     * 解析XML文件
     * 
     * @param file XML文件
     * @return XML数据映射
     */
    private Map<String, Object> parseXmlFile(MultipartFile file) {
        Map<String, Object> map = new HashMap<>();
        try {
            // 创建SAXReader对象
            SAXReader reader = new SAXReader();
            // 获取文件输入流
            try (InputStream inputStream = file.getInputStream()) {
                // 解析XML文档
                Document document = reader.read(inputStream);
                // 获取根元素
                Element root = document.getRootElement();
                // 解析XML数据
                map = parseXmlElement(root);
                
                // 记录解析到的基本信息
                if (root.element("Name") != null) {
                    map.put("Name", root.elementText("Name"));
                }
                if (root.element("Version") != null) {
                    map.put("Version", root.elementText("Version"));
                }
                if (root.element("Generator") != null) {
                    map.put("Generator", root.elementText("Generator"));
                }
                if (root.element("Unit") != null) {
                    map.put("Unit", root.elementText("Unit"));
                }
                if (root.element("Description") != null) {
                    map.put("Description", root.elementText("Description"));
                }
            }
        } catch (Exception e) {
            log.error("XML文件解析失败", e);
            return null;
        }
        return map;
    }
    
    /**
     * 递归解析XML元素
     * 
     * @param element XML元素
     * @return 解析结果
     */
    private Map<String, Object> parseXmlElement(Element element) {
        Map<String, Object> map = new HashMap<>();
        // 获取元素所有子节点
        List<Element> elements = element.elements();
        // 如果有子节点，递归解析
        if (!elements.isEmpty()) {
            int barCount = 0;
            int pieceCount = 0;
            int workCount = 0;
            
            for (Element child : elements) {
                String nodeName = child.getName();
                
                if ("Bar".equals(nodeName)) {
                    // 处理Bar节点
                    barCount++;
                    Map<String, Object> barMap = parseXmlElement(child);
                    map.put("Bar_" + barCount, barMap);
                } else if ("Piece".equals(nodeName)) {
                    // 处理Piece节点
                    pieceCount++;
                    Map<String, Object> pieceMap = parseXmlElement(child);
                    map.put("Piece_" + pieceCount, pieceMap);
                } else if ("Work".equals(nodeName)) {
                    // 处理Work节点
                    workCount++;
                    Map<String, Object> workMap = parseXmlElement(child);
                    map.put("Work_" + workCount, workMap);
                } else if ("Cut".equals(nodeName)) {
                    // 处理Cut节点（切割信息）
                    Map<String, Object> cutMap = new HashMap<>();
                    for (Element cutChild : child.elements()) {
                        cutMap.put(cutChild.getName(), cutChild.getTextTrim());
                    }
                    map.put("Cut", cutMap);
                } else if (child.elements().isEmpty()) {
                    // 如果没有子节点，直接获取文本值
                    map.put(nodeName, child.getTextTrim());
                } else {
                    // 其他情况，递归解析
                    Map<String, Object> childMap = parseXmlElement(child);
                    map.put(nodeName, childMap);
                }
            }
        } else {
            // 没有子节点，直接获取文本值
            map.put(element.getName(), element.getTextTrim());
        }
        return map;
    }
    
    /**
     * 保存所有数据，包括型材、切割和加工信息
     * 
     * @param xmlData XML数据
     * @param order 订单信息
     * @param userId 用户ID
     * @param userName 用户名
     * @return 保存的记录数数组 [型材数, 切割数, 加工数]
     */
    private int[] saveAllData(Map<String, Object> xmlData, ProductSalesOrder order, String userId, String userName) {
        List<CfProfileMaterial> materialList = new ArrayList<>();
        List<CfProfileCutDetail> cutDetailList = new ArrayList<>();
        List<CfProfileWorkDetail> workDetailList = new ArrayList<>();
        
        // 获取Order名称和单位
        String orderName = getStringValue(xmlData, "Name", "");
        String unit = getStringValue(xmlData, "Unit", "mm");
        String description = getStringValue(xmlData, "Description", "");
        
        log.info("解析优化单: {}, 单位: {}", orderName, unit);
        
        // 遍历所有Bar节点（原始型材）
        for (String key : xmlData.keySet()) {
            if (key.startsWith("Bar_")) {
                Map<String, Object> barMap = (Map<String, Object>) xmlData.get(key);
                
                // 提取原始型材基本信息
                String dxfName = getStringValue(barMap, "DXF_Name", "");
                String color = getStringValue(barMap, "Color", "");
                String barNumber = getStringValue(barMap, "BarNumber", "");
                double length = getDoubleValue(barMap, "Length", 0.0);
                double leftLength = getDoubleValue(barMap, "LeftLength", 0.0);
                double maxY = getDoubleValue(barMap, "MaxY", 0.0);
                double maxZ = getDoubleValue(barMap, "MaxZ", 0.0);
                
                // 创建原始型材基本信息
                CfProfileMaterial barMaterial = new CfProfileMaterial();
                barMaterial.setOrderId(order.getId());
                barMaterial.setOrderNo(order.getOrderNo());
                barMaterial.setProfileCode(dxfName);
                barMaterial.setProfileName(dxfName);
                barMaterial.setColor(color);
                barMaterial.setLength(length);
                barMaterial.setWidth(maxZ);
                barMaterial.setHeight(maxY);
                barMaterial.setQuantity(1);
                barMaterial.setLeftLength(leftLength);
                barMaterial.setRemark("原始型材: " + barNumber);
                barMaterial.setCreateTime(new Date());
                
                // 保存原始型材基本信息
                materialList.add(barMaterial);
                
                // 遍历所有Piece节点（切割后的子型材）
                for (String pieceKey : barMap.keySet()) {
                    if (pieceKey.startsWith("Piece_")) {
                        Map<String, Object> pieceMap = (Map<String, Object>) barMap.get(pieceKey);
                        
                        // 提取Piece信息
                        String pieceNumber = getStringValue(pieceMap, "PieceNumber", "");
                        String barCode = getStringValue(pieceMap, "BarCode", "");
                        String extraPie = getStringValue(pieceMap, "Extra_Pie", ""); // 位置信息
                        String ccCode = getStringValue(pieceMap, "Cc_code", "");     // 窗号
                        
                        // 提取切割信息
                        Map<String, Object> cutMap = pieceMap.get("Cut") != null ? 
                                (Map<String, Object>) pieceMap.get("Cut") : new HashMap<>();
                        double cutLength = getDoubleValue(cutMap, "Length", 0.0);
                        double sxB = getDoubleValue(cutMap, "sxB", 0.0);
                        double dxB = getDoubleValue(cutMap, "dxB", 0.0);
                        double sxC = getDoubleValue(cutMap, "sxC", 0.0);
                        double dxC = getDoubleValue(cutMap, "dxC", 0.0);
                        
                        // 创建切割信息
                        CfProfileCutDetail cutDetail = new CfProfileCutDetail();
                        cutDetail.setOrderId(order.getId());
                        cutDetail.setBarCode(barCode);
                        cutDetail.setLength(cutLength);
                        cutDetail.setSxB(sxB);
                        cutDetail.setDxB(dxB);
                        cutDetail.setSxC(sxC);
                        cutDetail.setDxC(dxC);
                        cutDetail.setPieceNumber(pieceNumber);
                        cutDetail.setPosition(extraPie);
                        cutDetail.setWindowNo(ccCode);
                        cutDetail.setCreateTime(new Date());
                        
                        // 保存切割信息
                        cutDetailList.add(cutDetail);
                        
                        // 收集加工信息
                        for (String workKey : pieceMap.keySet()) {
                            if (workKey.startsWith("Work_")) {
                                Map<String, Object> workMap = (Map<String, Object>) pieceMap.get(workKey);
                                
                                // 提取加工信息
                                String workName = getStringValue(workMap, "Name", "");
                                String workType = getStringValue(workMap, "Type", "");
                                String profiLav = getStringValue(workMap, "ProfiLav", "");
                                double positionX = getDoubleValue(workMap, "PositionX", 0.0);
                                double positionY = getDoubleValue(workMap, "PositionY", 0.0);
                                double positionZ = getDoubleValue(workMap, "PositionZ", 0.0);
                                
                                // 创建加工信息
                                CfProfileWorkDetail workDetail = new CfProfileWorkDetail();
                                workDetail.setOrderId(order.getId());
                                workDetail.setBarCode(barCode);
                                workDetail.setWorkName(workName);
                                workDetail.setWorkType(workType);
                                workDetail.setPositionX(positionX);
                                workDetail.setPositionY(positionY);
                                workDetail.setPositionZ(positionZ);
                                workDetail.setProfiLav(profiLav);
                                workDetail.setWindowNo(ccCode);
                                workDetail.setCreateTime(new Date());
                                
                                // 保存加工信息
                                workDetailList.add(workDetail);
                            }
                        }
                        
                        log.debug("添加型材切割: {}, 窗号: {}, 长度: {}, 位置: {}", 
                                barCode, ccCode, cutLength, extraPie);
                    }
                }
            }
        }
        
        // 批量保存原始型材数据
        if (!materialList.isEmpty()) {
            cfProfileMaterialService.saveBatch(materialList);
            
            // 创建型材ID与型材对象的映射，用于后续关联
            Map<String, String> profileCodeToIdMap = new HashMap<>();
            for (CfProfileMaterial material : materialList) {
                profileCodeToIdMap.put(material.getProfileCode(), material.getId());
            }
            
            // 更新切割信息中的型材ID
            for (CfProfileCutDetail cutDetail : cutDetailList) {
                // 这里使用型材编码关联，实际项目中可能需要更复杂的关联逻辑
                for (CfProfileMaterial material : materialList) {
                    if (material.getRemark().contains("原始型材")) {
                        cutDetail.setProfileId(material.getId());
                        break;
                    }
                }
            }
        }
        
        // 批量保存切割信息
        if (!cutDetailList.isEmpty()) {
            cfProfileCutDetailService.saveBatch(cutDetailList);
            
            // 创建条码与切割ID的映射，用于关联加工信息
            Map<String, String> barCodeToCutIdMap = new HashMap<>();
            for (CfProfileCutDetail cutDetail : cutDetailList) {
                barCodeToCutIdMap.put(cutDetail.getBarCode(), cutDetail.getId());
            }
            
            // 更新加工信息中的切割ID
            for (CfProfileWorkDetail workDetail : workDetailList) {
                String cutId = barCodeToCutIdMap.get(workDetail.getBarCode());
                if (cutId != null) {
                    workDetail.setCutId(cutId);
                }
            }
        }
        
        // 批量保存加工信息
        if (!workDetailList.isEmpty()) {
            cfProfileWorkDetailService.saveBatch(workDetailList);
        }
        
        return new int[] {materialList.size(), cutDetailList.size(), workDetailList.size()};
    }
    
    /**
     * 计算型材重量
     * 
     * @param length 长度(mm)
     * @param height 高度(mm)
     * @param width 宽度(mm)
     * @return 重量(kg)
     */
    private double calculateWeight(double length, double height, double width) {
        // 铝型材密度约为2.7g/cm³
        double density = 2.7; // g/cm³
        
        // 转换为cm
        double lengthCm = length / 10;
        double heightCm = height / 10;
        double widthCm = width / 10;
        
        // 计算体积(cm³)和重量(g)
        double volume = lengthCm * heightCm * widthCm;
        double weightG = volume * density;
        
        // 返回kg
        return weightG / 1000;
    }
    
    /**
     * 从Map中安全获取String值
     */
    private String getStringValue(Map<String, Object> map, String key, String defaultValue) {
        if (map != null && map.containsKey(key) && map.get(key) != null) {
            return map.get(key).toString();
        }
        return defaultValue;
    }
    
    /**
     * 从Map中安全获取Double值
     */
    private double getDoubleValue(Map<String, Object> map, String key, double defaultValue) {
        if (map != null && map.containsKey(key) && map.get(key) != null) {
            try {
                return Double.parseDouble(map.get(key).toString());
            } catch (NumberFormatException e) {
                log.warn("无法解析数值 {}: {}", key, map.get(key));
            }
        }
        return defaultValue;
    }
} 